/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
#if _LOCALDB
  using Oceanside.LocalDB;
#else
using Oceanside.RemoteDB;
#endif
namespace Oceanside
{
    class QuickDiscount : BindInterface
    {
        public QuickDiscount()
        {

        }

        override public System.Windows.Visibility IsVisible
        {
            get
            {
                try
                {
                    if (SHIFT.SelectedOrder != null && !SHIFT.SelectedOrder.CanCloseOrder &&
                        !SHIFT.SelectedOrder.IsClosed && SHIFT.Current.UserCanPromo())
                    {
                        return System.Windows.Visibility.Visible;
                    }
                    return System.Windows.Visibility.Hidden;
                }
                catch (Exception e) { Logging.LogException(e); return System.Windows.Visibility.Hidden; }
            }
        }


        private const string CONST_MESSAGE_REQUESTED_TOO_MUCH =
    "You requested to discount an amount greater than the total amount discountable on this check.  Some items such as alcohol may be configured as non-discountable due to local tax codes.";

        private const string CONST_MESSAGE_NO_DISCOUNTABLE_SALES = "The selected check does not contain any sales that are discountable.  Please keep in mind that some products such as alcohol are often configured as non-discountable per local and state tax laws.";



        override public void Clicked()
        {
            try
            {

                CompReasonsByButton compReasons =
                    new CompReasonsByButton(SHIFT.GlobalContext.COMP_ACCOUNTS
                        .Where(ca => (ca.IsPromo) && !ca.IsDeleted).ToList());

                compReasons.ShowDialog();

                if (CompReasonsByButton.LastResponse == UserResponse.ENTER)
                {
                    COMP_ACCOUNT ca = CompReasonsByButton.ChosenComp;

                    CheckOrItemYesNo ynb = new CheckOrItemYesNo();
                    ynb.ShowDialog();

                    if (CheckOrItemYesNo.LastResponse != ItemOrCheckResponse.EXIT)
                    {
                        List<SALE> compableSales;
                        bool isEntireCheck = CheckOrItemYesNo.LastResponse == ItemOrCheckResponse.CHECK;
                        if (!isEntireCheck)
                        {
                            SALE sale =
                                QuickOrderWindow.CustomerTicketListView.SelectedItem as SALE;
                            compableSales = new List<SALE>();

                            if (sale != null && sale.DiscountId == null)
                            {
                                if (sale.ProductIsDiscountable && !sale.IsGiftCardSale)
                                {
                                    if (sale.CountOrdered > 1)
                                    {
                                        HowManyBox hmb = new HowManyBox();
                                        hmb.ShowDialog();
                                        if (HowManyBox.LastNumberSelection > 0 && HowManyBox.LastNumberSelection <= sale.CountOrdered)
                                        {
                                            if (HowManyBox.LastNumberSelection == sale.CountOrdered)
                                            {
                                                compableSales.Add(sale);
                                            }
                                            else
                                            {
                                                compableSales.Add(SALE.SeparateSale(sale, true, HowManyBox.LastNumberSelection));
                                            }
                                        }
                                        else
                                        {
                                            UMD.ShowGuiMessageSTASafe_NOTHROW("You must select an amount greater than zero and less than or equal to "
                            + sale.CountOrdered + " for the currently selected product.");
                                        }
                                    }
                                    else
                                    {
                                        compableSales.Add(sale);
                                    }
                                }
                                else
                                {
                                    UMD.ShowGuiMessageSTASafe_NOTHROW("The item you selected cannot be discounted.");
                                }
                            }
                            else
                            {
                                UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot apply multiple discounts to the same item.");
                            }
                        }
                        else
                        {
                            compableSales =
                                SHIFT.SelectedOrder.ChecksCompableSales(0);
                        }

                        if (compableSales.Count != 0)
                        {
                            if (ca.IsVariableAmount)
                            {
                                CompPercentsBox cpb =
                                    new CompPercentsBox(
                                        new CompPercentsBox.OkClickedDelegateType(ProcessDiscount_NOTHROW),
                                        ca, compableSales, isEntireCheck);
                                cpb.ShowDialog();
                            }
                            else
                            {
                                ProcessDiscount_NOTHROW(ca.RateAsDollarOrPercent, true, ca, compableSales, isEntireCheck);
                            }
                        }
                    }
                }
                if (Constants.IsQuickServiceMode)
                {
                    CCBindings.SelectedSeatIndex = 0;
                    OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                    OrderApi.CustomerCheckListView.Items.Refresh();
                    PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
                }
            }
            catch (Exception ex)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_CCBIND_CALL_COMPPRODUCT, ex);
            }
        }

        /// <summary>
        /// This function is called after the user selects either a percentage or a dollar amount from a popup
        /// window.  In this function we apply a discount to the entire checks sales that have not already been discounted and are
        /// also marked as discountable.
        /// </summary>
        /// <param name="amountOrPercent"></param>
        /// <param name="wasPercent"></param>
        /// <param name="compAccount"></param>
        public static void ProcessDiscount_NOTHROW(
            decimal amountOrPercent,
            bool wasPercent,
            COMP_ACCOUNT compAccount,
            List<SALE> compableSales,
            bool isEntireCheck)
        {
            try
            {
                ///Make sure they didn't exit or chose a zero amount.
                if (amountOrPercent != 0)
                {
                    bool shouldContinue = true;

                    if (compableSales.Count() != 0)
                    {
                        decimal discountRate = 0M;

                        ///If the user chose to discount a specific dollar amount, then that means we need to reverse out a percentage
                        ///that we can apply to every sale.  The trick here is that this percentage will need to account for rounding 
                        ///issues and assure that in the end the discount amount is has reduced the check by exactly the amount the
                        ///user requested.
                        if (!wasPercent)
                        {
                            decimal totalCompable = compableSales.Sum(s => s.ActualPrice * s.CountOrdered);

                            ///Assure that the user did not attempt to comp an amount that 
                            ///is more than the amount they can actually comp. If they do this, then do not procede.
                            if (totalCompable < amountOrPercent)
                            {
                                UMD.ShowGuiMessageSTASafe_NOTHROW(CONST_MESSAGE_REQUESTED_TOO_MUCH);
                                shouldContinue = false;
                            }
                            else
                            {
                                ///Create the discount rate based upon the amount discountable and the amount they selected.
                                discountRate = amountOrPercent / totalCompable;
                            }
                        }
                        else
                        {
                            discountRate = (amountOrPercent / 100M);
                        }

                        ///Only if all conditions above have passed.
                        if (shouldContinue)
                        {
                            string notes = null;
                            if (compAccount.PromptUserToEnterNotes)
                            {
                                Oceanside.FullKeyboard.ActiveKeyboard.SetSmallMode(false);
                                Oceanside.FullKeyboard.ActiveKeyboard.SetMessage("Enter an Explanation:");
                                Oceanside.FullKeyboard.ActiveKeyboard.ShowMe();
                                if (Oceanside.FullKeyboard.LastResponse == UserResponse.ENTER)
                                {
                                    notes = Oceanside.FullKeyboard.GuiKeyPressedString;
                                }
                            }

                            Int64 managerId;
                            if (PosWindow.ManagerCardWasSwiped)
                            {
                                managerId = PosWindow.ManagerIdThatSwiped;
                            }
                            else
                            {
                                managerId = SHIFT.Current.UserId;
                            }

                            if (isEntireCheck)
                            {
                                foreach (SALE s in compableSales)
                                {
                                    if (s.ActualPrice != 0 && discountRate != 0)
                                    {
                                        s.DiscountRate = discountRate;

                                        ///Set the manager ID
                                        s.DiscountManagerId = managerId;

                                        ///Set the reason ID
                                        s.DiscountId = compAccount.Id;
                                        s.Notes = notes;
                                        s.DiscountAppliedAtCheckLevel = true;
                                    }
                                }
                            }
                            else
                            {
                                SALE s = compableSales.First();
                                if (s.ActualPrice != 0 && discountRate != 0)
                                {
                                    s.DiscountRate = discountRate;

                                    ///Set the manager ID
                                    s.DiscountManagerId = managerId;

                                    ///Set the reason ID
                                    s.DiscountId = compAccount.Id;
                                    s.Notes = notes;
                                    s.DiscountAppliedAtCheckLevel = false;
                                }
                                foreach (SALE modSale in s.MODSALES)
                                {
                                    if (modSale.ActualPrice != 0 && discountRate != 0)
                                    {
                                        modSale.DiscountRate = discountRate;
                                        modSale.DiscountId = compAccount.Id;
                                        modSale.DiscountManagerId = managerId;
                                        modSale.Notes = notes;
                                        modSale.DiscountAppliedAtCheckLevel = false;
                                    }
                                }
                            }

                            SHIFT.GlobalContext.SaveChanges();
                        }
                    }
                    else
                    {
                        UMD.ShowGuiMessageSTASafe_NOTHROW(CONST_MESSAGE_NO_DISCOUNTABLE_SALES);
                    }
                }
            }
            catch (Exception ex)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_CCBIND_COMP_PERCENT_OR_AMOUNT_WIN_CLOSE_CB, ex);
            }
        }
    }
}
